package com.haredot.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.haredot.dto.BindMenuSysDto;
import com.haredot.entity.Menu;
import com.haredot.exception.ServiceAccessException;
import com.haredot.mapper.MenuMapper;
import com.haredot.service.MenuService;
import com.haredot.vo.PageVo;
import com.haredot.vo.R;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Transactional(rollbackFor = Exception.class)
public class MenuServiceImpl implements MenuService {

    @Resource
    private MenuMapper menuMapper;

    @Override
    public R<?> saveMenu(Menu menu) {

        if (menuMapper.findMenuByName(menu.getMenuName()) != null) {
            return R.fail(R.StatusCode.BAD).data(Map.of("menuName", "菜单名已存在"));
        }

        // 插入表中
        int len = menuMapper.insert(menu);

        if (len != 1) throw new ServiceAccessException("数据库插入失败、期待影响 1 行，实际影响" + len + "行");

        return R.ok().data(menu);
    }

    @Override
    @Cacheable(value = "menu:all")
    public R<PageVo> queryMenusByPage(PageVo pageVo, Map<String, Object> params) {

        // 分页查询 数据
        PageInfo<Menu> pageInfo = PageHelper.startPage(pageVo)
                .doSelectPageInfo(() -> menuMapper.findMenusByCondition(params));

        // 将分页信息组装到 R 中
        pageVo.setTotal(pageInfo.getTotal()).setList(pageInfo.getList());

        return R.<PageVo>ok().data(pageVo);
    }

    @Override
    public R<?> bindSys(Long menuId, List<Long> sysIds) {
        // 根据 菜单 ID , 删除 (物理删除) 所有绑定的系统
        menuMapper.removeSysByMenuId(menuId);
        // 如果 传入的系统 ID 不为空，则 继续绑定系统
        if (sysIds != null && !sysIds.isEmpty()) {
            menuMapper.batchInsertSysByMenuId(menuId, sysIds);
        }
        return R.ok().build();
    }

    @Override
    public R<?> batchRemoveMenus(List<Long> menuIds) {

        int len = menuMapper.batchRemoveByMenus(menuIds);

        if (len != menuIds.size()) {
            throw new ServiceAccessException("批量删除失败、期待删除" + menuIds.size() + "条记录、实际删除" + len + "条");
        }
        return R.ok().build();
    }

    @Override
    public R<?> updateMenu(Menu menu) {
        // 根据菜单名、查询菜单是否已存在
        Menu menuByName = menuMapper.findMenuByName(menu.getMenuName());

        if (menuByName != null && !Objects.equals(menuByName.getId(), menu.getId())) {
            return R.fail(R.StatusCode.BAD).data(Map.of("menuName", "菜单名已存在"));
        }
        menu.setUpdateTime(LocalDateTime.now());
        int len = menuMapper.updateMenuById(menu);
        return R.ok().build();
    }

    @Override
    public R<BindMenuSysDto> querySysBindMenuListBySysId(Long sysId) {

        List<BindMenuSysDto> list = menuMapper.findSysBindMenuListBySysId(sysId);

        return R.<BindMenuSysDto>ok().data(list);
    }

    @Override
    public R<?> removeMenu(Long menuId) {

        int len = menuMapper.deleteById(menuId);

        if (len != 1) throw new ServiceAccessException("删除菜单失败、期待删除 1 条、实际删除了" + len + "条");

        return R.ok().build();
    }
}
